package com.vecspace.dicttable;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.apache.logging.log4j.core.util.SystemNanoClock;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
/**
 * @author: wanghua
 */
public class DictAll {
	private static Object lockObj = new Object();
	public static ICodeDataSource s_dmDataSource;

	public static ICodeDataSource getDmDataSource() {
		return s_dmDataSource;
	}

	public static void setDmDataSource(ICodeDataSource dmDataSource) {
		s_dmDataSource = dmDataSource;
	}
	
	private static String dictTableName = "";
	private static String codeTypeField = "";
	private static String codeField = "";
	private static String nameField = "";
	private static String parentField = "";
	private static String orderByField = "";
	
//	private static Map<String,CodeTable> tables = new HashMap<String,CodeTable>();//tableName,DMTable
//	
//	
//	static{
//		ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
//		scheduler.schedule(new Runnable() {			
//			@Override
//			public void run() {
//				clear();				
//			}
//		}, 24*3600, TimeUnit.SECONDS);//TODO 测试后修改时间间隔为 24*3600秒;
//	}
	
	private static Cache<String,CodeTable> _cache;
	
	private static Cache<String,CodeTable> getCache() {
		if(_cache == null) {
			synchronized(DictAll.class) {
				if(_cache == null) {
					Caffeine<Object, Object> caffeine = Caffeine.newBuilder();
					int timeoutSeconds = 5 * 60; //5分钟过期
					caffeine.expireAfterWrite(timeoutSeconds, TimeUnit.SECONDS);		
					_cache = caffeine.build();	
				}
			}
		}		
		return _cache;
	}
	
	public static void clear(){
		if(_cache == null) {
			return;
		}
		
		_cache.invalidateAll();
		System.out.println(new Date().toString()+":已经清空所有缓存的代码");
	}
	
	/**
	 * 根据码表中的编码获取名称
	 * @param codeType 编码类型
	 * @param code  编码值
	 * @return 编码对应的名称
	 * @author: wanghua
	 */
	public static String getItemName(String codeType, String code){
		return getCachedItemName(codeType, code);
	}
	
	/**
	 * 根据表名，代码，获取代码对应的名称
	 * @param tableName 代码表名
	 * @param code 代码
	 * @return 名称
	 * @author: wanghua
	 */
	public static String getCachedItemName(String codeType, String code){		
		CodeItem item = getCachedItem(codeType, code);
		if(item == null) {
			return code;
		}
		else {
			return item.getName(); 
		}
	}
	
	/** 根据表名，代码，获取代码对应的DMItem
	 * @param tableName 代码表名
	 * @param code 代码
	 * @return 名称
	 * @author: wanghua
	 */
	public static CodeItem getCachedItem(String codeType, String code){
		if(s_dmDataSource == null) {
			return null;
		}
		if(code == null || code.toString().length()==0) {
			return null;
		}
		Cache<String,CodeTable> cache = getCache();
		CodeTable table = cache.getIfPresent(codeType);
		if(table == null){
			synchronized(lockObj){
				if(table == null){
					try{
						table = s_dmDataSource.fillDMTableFromDictAll(codeType, dictTableName, 
							codeTypeField, codeField, nameField, parentField, orderByField);
						cache.put(codeType, table);
					}catch(Exception e){
						System.out.println(e.getMessage());
					}
				}
			}
		}
		if(table != null){
			return table.getItem(code);
		}
		return null;
	} 
	 
	/**
	 * 获取指定表的所有字典值的列表（不使用缓存数据）
	 * dmClazz必须包含CodeTableInfoAnnotation注解
	 * @param dmClazz dmClazz必须包含CodeTableInfoAnnotation注解
	 * @return 
	 * @author: wanghua
	 */
	public List<CodeItem> getItems(Class<?> dmClazz){
		CodeTableInfoAnnotation anno = dmClazz.getAnnotation(CodeTableInfoAnnotation.class);
		if(anno != null){
			List<CodeItem> list = getItems(anno.TableName());
			return list;
		}else {
			return null;
		}
	}
	
	/**
	 * 获取指定表的所有字典值的列表
	 * @param tableName
	 * @param idField
	 * @param codeField
	 * @param nameField
	 * @param orderByField
	 * @return 
	 * @author: wanghua
	 */
	public static List<CodeItem> getItems(String codeType, boolean userCache){
		if(s_dmDataSource == null) {
			return new ArrayList<CodeItem>(); 
		}
		codeType = codeType.toUpperCase();
		CodeTable table = null;
		Cache<String,CodeTable> cache = getCache();
		if(userCache){ //如果使用缓存，则首先从缓存中获取数据，否则从数据库中读取数据

			table = cache.getIfPresent(codeType);
		}
		if(table == null){
			synchronized(DictAll.class){
				if(table == null){
					try{
						table = s_dmDataSource.fillDMTableFromDictAll(codeType, dictTableName, 
							codeTypeField, codeField, nameField, parentField, orderByField);
						cache.put(codeType, table);
					}catch(Exception e){
						System.out.println(e.getMessage());
					}
				}
			}
		}
		if(table != null){
			return table.getItemlist();
		}else {
			return new ArrayList<CodeItem>(); 
		}
	}
	
	/**获取指定表的所有字典值的列表（不使用缓存数据）*/
	public static List<CodeItem> getItems(String codeType){
		return getItems(codeType, false);
	}
	
	public static void clearDMTable(String codeType){
		codeType = codeType.toUpperCase();
		Cache<String,CodeTable> cache = getCache();
		cache.invalidate(codeType);
	}
	
	public static String createHtmlSelectOptions(String codeType, String selectedValue, boolean useCache){
		StringBuilder sbText = new StringBuilder();
		List<CodeItem> items = getItems(codeType);
		if (items==null)
		{
			return null;
		} else
		{
			for(CodeItem item : items){
				String selected = "";
				if(selectedValue != null && selectedValue.equals(item.getCode())){
					selected = "selected=\"selected\"";
				}
				sbText.append("<option ").append(selected).append(" value=\"");
				sbText.append(item.getCode()).append("\">").append(item.getName()).append("</option>");
			}
		}
		
		return sbText.toString();
	}
	
	public static String createHtmlSelectOptions(String codeType, String selectedValue){
		return createHtmlSelectOptions(codeType, selectedValue, false);
	}

	public String getDictTableName() {
		return dictTableName;
	}

	public void setDictTableName(String dictTableName) {
		DictAll.dictTableName = dictTableName;
	}
	 

	public String getCodeTypeField() {
		return codeTypeField;
	}

	public void setCodeTypeField(String codeTypeField) {
		DictAll.codeTypeField = codeTypeField;
	}

	public static String getCodeField() {
		return codeField;
	}

	public void setCodeField(String codeField) {
		DictAll.codeField = codeField;
	}

	public static String getNameField() {
		return nameField;
	}

	public void setNameField(String nameField) {
		DictAll.nameField = nameField;
	}
	public static String getParentField() {
		return parentField;
	}

	public static void setParentField(String parentField) {
		DictAll.parentField = parentField;
	}

	public String getOrderByField() {
		return orderByField;
	}

	public void setOrderByField(String orderByField) {
		DictAll.orderByField = orderByField;
	}

}
